package com.vviton.zyhj.common.utils.hbase;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;

import com.vviton.zyhj.common.utils.hbase.annotation.HColumn;
import com.vviton.zyhj.common.utils.hbase.annotation.HCurrentClusterIndex;
import com.vviton.zyhj.common.utils.hbase.annotation.HRowKey;
import com.vviton.zyhj.common.utils.hbase.annotation.HTable;

/**
 *
 * ClassName: HBaseUtils <br/>
 * Function: HBase工具包. <br/>
 * Date: 2016年3月10日 下午4:51:20 <br/>
 *
 * @author qiaocf
 * @version 1.0
 * @since JDK 1.7
 */
public abstract class HBaseUtils {

    /** ROW_KEY_SEPARATOR **/
    public static final String ROW_KEY_SEPARATOR = "~";

    /** 日期模板 **/
    public static final String CLUSTER_DATE_FORMAT = "yyyyMMddHHmmssSSS";

    /**
     *
     * formRowKey,(formRowKey). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param entity 实体
     * @return String
     * @since JDK 1.7
     */
    public static String formRowKey(Object entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        String[] rowKeyElems = getHRowKeyElements(entity.getClass());
        StringBuilder sb = new StringBuilder();
        SimpleDateFormat sdf = new SimpleDateFormat(CLUSTER_DATE_FORMAT);
        try {
            for (String elem : rowKeyElems) {
                for (Field field : fields) {
                    if (field.isAnnotationPresent(HColumn.class)) {
                        HColumn column = field.getAnnotation(HColumn.class);
                        if (column.columnName().equalsIgnoreCase(elem)) {
                            field.setAccessible(true);
                            Object val = field.get(entity);
                            String elemVal = "";
                            if (field.getType().isAssignableFrom(Date.class)) {
                                if (val != null) {
                                    elemVal = sdf.format(val);
                                }
                            } else {
                                elemVal = val == null ? "" : val.toString();
                            }
                            sb.append(elemVal + ROW_KEY_SEPARATOR);
                            break;
                        }
                    }
                }
            }
            if (sb.toString().length() > 0) {
                return sb.toString().substring(0, sb.toString().length() - 1);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    /**
     *
     * formColumnMap,(formColumnMap). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param entity 实体
     * @return Map<String, Object>
     * @since JDK 1.7
     */
    public static Map<String, Object> formColumnMap(Object entity) {
        String[] clusters = getHClusters(entity.getClass());
        Integer currentClusterIndex = getHCurrClusterIndex(entity);
        String currentCluster = clusters[currentClusterIndex];
        Map<String, Object> columnMap = new HashMap<String, Object>();
        Field[] fields = entity.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                if (field.isAnnotationPresent(HColumn.class) && !field.isAnnotationPresent(HRowKey.class)) {
                    HColumn column = field.getAnnotation(HColumn.class);
                    String defVal = column.defVal();
                    String[] refClusters = column.refClusters();
                    for (String cluster : refClusters) {
                        if (cluster.equalsIgnoreCase(currentCluster)) {
                            field.setAccessible(true);
                            Object val = field.get(entity);
                            if (val == null) {
                                val = defVal;
                            }
                            columnMap.put(currentCluster + "." + column.columnName(), val);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return columnMap;
    }

    /**
     *
     * getHCurrClusterIndex,(getHCurrClusterIndex). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param entity 实体
     * @return Integer
     * @since JDK 1.7
     */
    private static Integer getHCurrClusterIndex(Object entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        Integer currentClusterIndex = 0;
        try {
            for (Field field : fields) {
                if (field.isAnnotationPresent(HCurrentClusterIndex.class)) {
                    field.setAccessible(true);
                    Object val = field.get(entity);
                    currentClusterIndex = val == null ? 0 : Integer.parseInt(val.toString());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return currentClusterIndex;
    }

    /**
     *
     * getHClusters,(getHClusters). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param clazz 类名
     * @return String[]
     * @since JDK 1.7
     */
    public static String[] getHClusters(Class<?> clazz) {
        if (clazz.isAnnotationPresent(HTable.class)) {
            HTable table = clazz.getAnnotation(HTable.class);
            return table.clusters();
        }
        return null;
    }

    /**
     *
     * getHRowKeyElements,(getHRowKeyElements). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param clazz 类名
     * @return String[]
     * @since JDK 1.7
     */
    private static String[] getHRowKeyElements(Class<?> clazz) {
        if (clazz.isAnnotationPresent(HTable.class)) {
            HTable table = clazz.getAnnotation(HTable.class);
            return table.rowKeyElements();
        }
        return null;
    }

    /**
     *
     * getHTableName,(getHTableName). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param clazz 类名
     * @return String
     * @since JDK 1.7
     */
    public static String getHTableName(Class<?> clazz) {
        if (clazz.isAnnotationPresent(HTable.class)) {
            HTable table = clazz.getAnnotation(HTable.class);
            return table.tableName();
        }
        return null;
    }

    /**
     *
     * formHObjectByRetMap,(formHObjectByRetMap). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param values 值
     * @param clazz 类名
     * @return Object
     * @since JDK 1.7
     */
    @SuppressWarnings("rawtypes")
    public static Object formHObjectByRetMap(Map<String, Object> values, Class<?> clazz) {
        try {
            Object o = clazz.newInstance();
            Field[] fields = clazz.getDeclaredFields();
            String currCluster = "";
            if (values != null) {
                Iterator<Entry<String, Object>> iter = values.entrySet().iterator();
                while (iter.hasNext()) {
                    Entry e = iter.next();
                    String key = (String) e.getKey();
                    Object value = e.getValue();
                    if (key != null && value != null) {
                        for (Field field : fields) {
                            if (field.isAnnotationPresent(HColumn.class)) {
                                HColumn column = field.getAnnotation(HColumn.class);
                                String columnName = column.columnName();
                                String[] keyPro = key.split("\\.");
                                String proName = keyPro[keyPro.length - 1];
                                currCluster = keyPro[0];
                                if (StringUtils.isNotBlank(proName) && proName.equalsIgnoreCase(columnName)) {
                                    field.setAccessible(true);
                                    field.set(o, value);
                                }
                            }
                        }
                    }
                }
            }
            String[] clusters = getHClusters(clazz);
            Integer currentClusterIndex = 0;
            if (StringUtils.isNotBlank(currCluster) && clusters.length > 0) {
                for (int i = 0; i < clusters.length; i++) {
                    if (currCluster.equalsIgnoreCase(clusters[i])) {
                        currentClusterIndex = i;
                    }
                }
            }

            for (Field field : fields) {
                if (field.isAnnotationPresent(HCurrentClusterIndex.class)) {
                    field.setAccessible(true);
                    field.set(o, currentClusterIndex);
                }
            }
            return o;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     *
     * syncObjectRowKey,(syncObjectRowKey). <br/>
     * Author: qiaocf <br/>
     * Create Date: 2016年3月10日 <br/>
     * ===============================================================<br/>
     * Modifier: qiaocf <br/>
     * Modify Date: 2016年3月10日 <br/>
     * Modify Description: <br/>
     * ===============================================================<br/>
     *
     * @param rowKey rowKey
     * @param entity 实体
     * @return Object
     * @since JDK 1.7
     */
    public static Object syncObjectRowKey(String rowKey, Object entity) {
        Field[] fields = entity.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {
                if (field.isAnnotationPresent(HRowKey.class)) {
                    field.setAccessible(true);
                    field.set(entity, rowKey);
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return entity;
    }

}
